home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / kgdb-4.5 / ds3100.md / gdb / mips_kgdb_remote.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-11-18  |  37.6 KB  |  1,536 lines

  1. /* Memory-access and commands for inferior process, for GDB.
  2.    Copyright (C)  1988 Free Software Foundation, Inc.
  3.  
  4. GDB is distributed in the hope that it will be useful, but WITHOUT ANY
  5. WARRANTY.  No author or distributor accepts responsibility to anyone
  6. for the consequences of using it or for whether it serves any
  7. particular purpose or works at all, unless he says so in writing.
  8. Refer to the GDB General Public License for full details.
  9.  
  10. Everyone is granted permission to copy, modify and redistribute GDB,
  11. but only under the conditions described in the GDB General Public
  12. License.  A copy of this license is supposed to have been given to you
  13. along with GDB so you can know your rights and responsibilities.  It
  14. should be in a file named COPYING.  Among other things, the copyright
  15. notice and this notice must be preserved on all copies.
  16.  
  17. In other words, go ahead and share GDB, but don't try to stop
  18. anyone else from sharing it farther.  Help stamp out software hoarding!
  19. */
  20. /*#define MACH_NUM_GPRS 32
  21. #define MACH_NUM_FPRS 32*/
  22. #include <stdio.h>
  23. #include <sprite.h>
  24. #include <signal.h>
  25. #include <sys/types.h>
  26. #include <sys/file.h>
  27. #include <errno.h>
  28. /*#include <kernel/ds3100.md/machConst.h>*/
  29. #include <kernel/machTypes.h>
  30. #include <kernel/dbg.h>
  31. #include <kernel/procTypes.h>
  32.  
  33. #include "defs.h"
  34. #include <sys/param.h>
  35. #include "frame.h"
  36. #include "inferior.h"
  37. #include "value.h"
  38. #include "expression.h"
  39. /*#include "wait.h"*/
  40. #include <sys/wait.h>
  41. #include "sprite.h"
  42. #include "target.h"
  43.  
  44. /*
  45.  * The data cache is just an array of characters.
  46.  */
  47. static char *dataCache;
  48.  
  49. /*
  50.  * There is information about kept about each cache block.
  51.  */
  52. typedef    struct {
  53.     int        version;    /* Version number of this cache block. */
  54.     char    *realAddr;    /* Actual address of data stored in the block.*/
  55. } CacheInfo;
  56. static CacheInfo    *cacheInfo;
  57. static int    currentVersion = 1;
  58.  
  59. /*
  60.  * Useful macros
  61.  * ERROR_NO_ATTACHED_HOST - Remote an error and abort if no host is
  62.  *                currently attached.
  63.  * MARK_DISCONNECTED - Mark a host a disconnected and free up state.
  64.  */
  65.  
  66. #define ERROR_NO_ATTACHED_HOST \
  67.     if (!hostName) error("No machine attached.");
  68.  
  69. #define MARK_DISCONNECTED  {     \
  70.     initialized = 0;          \
  71.     inferior_pid = 0;        \
  72.     hostName = (char *) 0;     \
  73.     free(dataCache);      \
  74.     free(cacheInfo);      \
  75.     }
  76.  
  77. extern struct target_ops remote_ops;    /* Forward decl */
  78. int remote_debugging = 0;
  79.  
  80. /*
  81.  * Hostname of attached remote hosts.  Error otherwise.
  82.  */
  83.  
  84. char *hostName;
  85.  
  86. static    int    initialized = 0; /* Set to true when remote connection is
  87.                   * initialized. */
  88.  
  89. /*
  90.  * Table mapping kernel exceptions into Unix signals.  
  91.  */
  92.  
  93. struct sig_mapping_struct {
  94.     char     *sig_name;    /* Print string for signal. */
  95.     int     dbgSig;     /* Boolean - A signal used by the debugger. */
  96.     int     unixSignal;     /* Unix signal equalient. */
  97. } sig_mapping[] =  {
  98. /* 0 */ { "Interrupt pending", 0, SIGILL },
  99. /* 1 */ { "TLB modified fault", 0, SIGSEGV },
  100. /* 2 */ { "TLB miss on load or ifetch", 0, SIGSEGV },
  101. /* 3 */ { "TLB miss on a store", 0, SIGSEGV },
  102. /* 4 */ { "Address error on a load or ifetch", 0, SIGBUS },
  103. /* 5 */ { "Address error on a store", 0, SIGBUS },
  104. /* 6 */ { "Bus error on an ifetch", 0, SIGBUS },
  105. /* 7 */ { "Bus error on a load or store", 0, SIGBUS },
  106. /* 8 */ { "System call", 0, SIGSYS },
  107. /* 9 */ { "Breakpoint",  1, SIGTRAP },
  108. /* 10 */ { "Reserved Instruction", 0, SIGILL },
  109. /* 11 */ { "Coprocessor Unusable",  0, SIGILL },
  110. /* 12 */ { "Arithmetic overflow",  0, SIGILL },
  111. /* 13 */ { "UNKNOWN EXCEPTION", 0, SIGSEGV },
  112. };
  113.  
  114. #define    NUM_SIG_MAPS    (sizeof(sig_mapping)/sizeof(sig_mapping[0]))
  115.  
  116.  
  117.  
  118. #define    PBUFSIZ    1024
  119.  
  120. /* Maximum number of bytes to read/write at once.  The value here
  121.    is chosen to fill up a packet (the headers account for the 32).  */
  122. #define MAXBUFBYTES ((PBUFSIZ-32)/2)
  123.  
  124.  
  125. /*
  126.  *----------------------------------------------------------------------
  127.  *
  128.  * Regnum_to_index --
  129.  *
  130.  *    Function mapping a gdb register number into an index.
  131.  *
  132.  * Results:
  133.  *    Index to Mach_State structure when treated as an array on ints.
  134.  *
  135.  * Side effects:
  136.  *    None.
  137.  *
  138.  *----------------------------------------------------------------------
  139.  */
  140. static int 
  141. Regnum_to_index(r) 
  142.     int    r;
  143.   Mach_RegState bud;
  144. #define    O(f)    ((int)&(bud.f)/sizeof(int))
  145.   if (r < 32) return O(regs[r]);
  146.   if (r < PC_REGNUM) return  O(fpRegs[r-32]);
  147.   if (r == PC_REGNUM) return O(pc);
  148.   if (r == HI_REGNUM) return O(mfhi);
  149.   if (r == LO_REGNUM) return O(mflo);
  150.   if (r == FCRCS_REGNUM) return O(fpStatusReg);
  151.   return -1;
  152. #undef O
  153. };
  154. int lastPid = -1;    /* Process ID of process being examined. -1
  155.                  * means process causing trap. */
  156.  
  157. /*
  158.  * The following variables are sued when using the core memory interface
  159.  * rather than active ethernet debugging.
  160.  */
  161. static int remoteCoreChan = -1;    /* Open file descriptor of core file. -1 
  162.                  * means no file open. */
  163. static char *remoteCoreFile;    /* Malloced name of core file. */
  164. static int remoteOffset;    /* Offset used to convert addresses to 
  165.                  * offsets into core file. */
  166. StopInfo    remoteStopInfo;    /* Current Dbg_StopInfo from core file. */
  167. static Dbg_DumpBounds remoteBounds;  /* Dump bounds from core file. */
  168.  
  169. /*
  170.  * IN_CORE_FILE - Returns TRUE if address is in the corefile.
  171.  */
  172. #define    IN_CORE_FILE(addr) ((addr) >= (CORE_ADDR) remoteBounds.kernelCodeStart\
  173.       && ((addr) < (CORE_ADDR) remoteBounds.fileCacheStart + \
  174.                           remoteBounds.fileCacheSize))
  175.  
  176. /*
  177.  *----------------------------------------------------------------------
  178.  *
  179.  * remote_core_file_command --
  180.  *
  181.  *    kgdb.sun4 core_file command.
  182.  *
  183.  * Results:
  184.  *    None.
  185.  *
  186.  * Side effects:
  187.  *    None.
  188.  *
  189.  *----------------------------------------------------------------------
  190.  */
  191.  
  192. void
  193. remote_core_file_command (filename, from_tty)
  194.      char *filename;
  195.      int from_tty;
  196. {
  197.   /* Discard all vestiges of any previous core file
  198.      and mark data and stack spaces as empty.  */
  199.  
  200.   if (remoteCoreFile)
  201.     free (remoteCoreFile);
  202.   remoteCoreFile = 0;
  203.  
  204.   if (remoteCoreChan >= 0)
  205.     close (remoteCoreChan);
  206.   remoteCoreChan = -1;
  207.   if (filename == 0) {
  208.     printf ("Corefile cleared.\n");
  209.     return;
  210.   }
  211.  
  212.   filename = tilde_expand (filename);
  213.   make_cleanup (free, filename);
  214.  
  215.   remoteCoreChan = open (filename, O_RDONLY, 0);
  216.   if (remoteCoreChan < 0)
  217.     perror_with_name (filename);
  218.  
  219.   {
  220.     /*
  221.      * Read the StopInfo and bounds and start the debugging session.
  222.      */
  223.     int val;
  224.     val = myread (remoteCoreChan, &remoteStopInfo, sizeof remoteStopInfo);
  225.     if (val < 0)
  226.       perror_with_name (filename);
  227.     val = myread (remoteCoreChan, &remoteBounds, sizeof remoteBounds);
  228.     if (val < 0)
  229.       perror_with_name (filename);
  230.     remote_debugging = 1;
  231.     remoteOffset = remoteBounds.kernelCodeStart - sizeof(remoteStopInfo) -
  232.             sizeof(remoteBounds);
  233.     start_remote();
  234.   }
  235. }
  236.  
  237.  
  238. /* Open a connection to a remote debugger.
  239.    NAME is the filename used for communication.  */
  240.  
  241. void
  242. remote_open (name, from_tty)
  243.      char *name;
  244.      int from_tty;
  245. {
  246.   if (remoteCoreChan >= 0) {
  247.       error("Can't attach a machine when using a corefile\n");
  248.       return;
  249.   }
  250.  
  251.   hostName = savestring(name,strlen(name));
  252.   if (from_tty)
  253.     printf ("Remote debugging using %s\n", name);
  254.   push_target (&remote_ops);
  255.   remote_debugging = 1;
  256.   start_remote ();
  257. }
  258.  
  259. char *
  260. remote_version()
  261. {
  262.   static char    version[1024];
  263.   
  264.   ERROR_NO_ATTACHED_HOST;
  265.   Kdbx_Trace(DBG_GET_VERSION_STRING, 0, version, 1024);
  266.   return version;
  267. }
  268.  
  269.  
  270.  
  271. /* Tell the remote machine to resume.  */
  272.  
  273. int     step_addr, step_addr_contents[2];
  274.  
  275. void
  276. remote_resume (step, signal)
  277.      int step, signal;
  278. {
  279.   
  280.   if (signal)
  281.     error ("Can't send signals to a remote system.");
  282.   ERROR_NO_ATTACHED_HOST;
  283.   step_addr = -2;
  284.   if (step) {
  285.     if (Kdbx_Trace( DBG_SINGLESTEP, 0, 0, sizeof(int)) < 0) {
  286.       error("error trying to continue process\n");
  287.     }
  288.   } else {
  289.     if (Kdbx_Trace( DBG_CONTINUE, 0, 0, sizeof(int)) < 0) {
  290.       error("error trying to continue process\n");
  291.     }
  292.   }
  293.   
  294. }
  295.  
  296. /* Wait until the remote machine stops, then return,
  297.    storing status in STATUS just as `wait' would.  */
  298.  
  299. int
  300. remote_wait (status)
  301.      union wait *status;
  302. {
  303.   StopInfo    stopInfo;
  304.   int        cause;
  305.   int    text_size;
  306.   extern CORE_ADDR text_start, text_end;
  307. #if 0
  308.   if (remoteCoreChan >= 0) {
  309.     /*
  310.      * Debugging using core file, just set text_{start, end} and
  311.      * returned stopped signal.
  312.      */
  313.     status->w_status = 0;
  314.     status->w_stopval = WSTOPPED;
  315.     cause = remoteStopInfo.trapType;
  316.     status->w_stopsig = sig_mapping[cause].unixSignal;
  317.     if ((lastPid == -1) && !sig_mapping[cause].dbgSig) { 
  318.       printf("Kernel returns with signal (%d) %s\n", cause,
  319.          sig_mapping[trap].sig_name);
  320.     }
  321.     text_start = remoteBounds.kernelCodeStart;
  322.     text_end = remoteBounds.kernelCodeStart + remoteBounds.kernelCodeSize;
  323.     return status->w_stopsig;
  324.   }
  325. #endif
  326.   ERROR_NO_ATTACHED_HOST;
  327.   
  328.   if (Kdbx_Trace(DBG_GET_STOP_INFO, (char *) 0, (char *)&stopInfo,
  329.          sizeof(stopInfo)) != 0) {
  330.     error("Can't get stop info\n");
  331.   }
  332. #if 0
  333.   if (Kdbx_Trace(DBG_GET_DUMP_BOUNDS, (char *) 0, (char *)&remoteBounds,
  334.          sizeof(remoteBounds)) != 0) {
  335.     error("Can't get dump bounds\n");
  336.   }
  337. #endif
  338.   status->w_status = 0;
  339.   status->w_stopval = WSTOPPED;
  340.   cause = stopInfo.trapType;
  341.   status->w_stopsig = sig_mapping[cause].unixSignal;
  342.   if ((lastPid != -1) && !sig_mapping[cause].dbgSig) { 
  343.     printf("Kernel returns with signal (%d) %s\n",stopInfo.trapType,
  344.        sig_mapping[cause].sig_name);
  345.   }
  346.  
  347.   text_start = stopInfo.codeStart;
  348. #if 0  
  349.   text_size = remoteBounds.kernelCodeSize;
  350. #else
  351.   text_size = 0xc0000000 - text_start;
  352. #endif
  353.   text_end = text_start+text_size;
  354.   return status->w_stopsig;
  355. }
  356.  
  357. /* Read the remote registers into the block REGS.  */
  358. #define FIRST_LOCAL_REGNUM    16
  359. void
  360. remote_fetch_registers (regno)
  361.      int regno;
  362. {
  363.   StopInfo    stopInfo;
  364.   char regs[REGISTER_BYTES];
  365.   int i;
  366. #if 0
  367.   if (remoteCoreChan >= 0) {
  368.     
  369.     bcopy(remoteStopInfo.regs.globals,regs,4*8);
  370.     bcopy(remoteStopInfo.regs.ins,regs+4*8,4*8);
  371.     ((int *)regs)[Y_REGNUM] = remoteStopInfo.regs.y; 
  372.     ((int *)regs)[PS_REGNUM] = remoteStopInfo.regs.curPsr; 
  373.     ((int *)regs)[PC_REGNUM] = remoteStopInfo.regs.pc; 
  374.     ((int *)regs)[NPC_REGNUM] = remoteStopInfo.regs.nextPc; 
  375.     remote_read_bytes(remoteStopInfo.regs.ins[6], 
  376.               ((int *) regs) + FIRST_LOCAL_REGNUM,4*16);
  377.     return;
  378.   }
  379. #endif
  380.   ERROR_NO_ATTACHED_HOST;
  381.   Kdbx_Trace(DBG_GET_STOP_INFO, (char *) 0, (char *)&stopInfo,
  382.          sizeof(stopInfo));
  383.   bcopy(stopInfo.regs.regs,regs,4*32);
  384.   bcopy(stopInfo.regs.fpRegs,regs+4*32,4*32);
  385.   ((int *)regs)[PC_REGNUM] = (int) stopInfo.regs.pc; 
  386.   ((int *)regs)[FP_REGNUM] = (int) stopInfo.regs.regs[29]; 
  387.   ((int *)regs)[SP_REGNUM] = (int) stopInfo.regs.regs[29]; 
  388.   ((int *)regs)[HI_REGNUM] = stopInfo.regs.mfhi; 
  389.   ((int *)regs)[LO_REGNUM] = stopInfo.regs.mflo; 
  390.   ((int *)regs)[FCRCS_REGNUM] = stopInfo.regs.fpStatusReg; 
  391.   for (i = 0; i < NUM_REGS; i++)
  392.     supply_register (i, ®s[REGISTER_BYTE(i)]);
  393. }
  394.  
  395.  
  396. int
  397. remote_attach(pid)
  398.      int    pid;
  399. {
  400.   int    status;
  401.   struct expression *expr;
  402.   register struct cleanup *old_chain;
  403.   register value val;
  404.   int    machRegStateAddr;
  405.   Proc_ControlBlock    *procPtr;
  406.   Mach_RegState machRegState;
  407.   char    exp[128];
  408.   
  409.   ERROR_NO_ATTACHED_HOST;
  410.   if (pid != lastPid) {
  411.     Kdbx_Trace(DBG_SET_PID, &pid, 0,sizeof(int));
  412.     lastPid = pid;
  413.   }
  414.   start_remote();
  415.   return 1;
  416. }
  417.  
  418. void
  419. remote_detach(args, from_tty)
  420.      char *args;
  421.      int from_tty;
  422. {
  423.   int cur_pc;
  424.   
  425.   ERROR_NO_ATTACHED_HOST;
  426.   cur_pc = read_pc();
  427.   if (args) 
  428.     Kdbx_Trace(DBG_DETACH, &cur_pc, 0, sizeof(int));
  429.   remote_clean_up();
  430.   pop_target ();
  431.   remote_debugging = 0;
  432.   if (from_tty)
  433.     printf("Ending remote debugging.\n");
  434. }
  435.  
  436.  
  437.  
  438. /* Read a word from remote address ADDR and return it.
  439.    This goes through the data cache.  */
  440.  
  441. int
  442. remote_fetch_word (addr)
  443.      CORE_ADDR addr;
  444. {
  445.   
  446.   int buffer;
  447.   extern CORE_ADDR text_start, text_end;
  448.   
  449.   ERROR_NO_ATTACHED_HOST;
  450.   if (addr >= text_start && addr < text_end)
  451.     {
  452.       if (Kdbx_Trace(DBG_INST_READ, addr, &buffer, sizeof(int)) != 0) {
  453.     errno = EIO;
  454.     return 0;
  455.       }
  456.       return buffer;
  457.     }
  458.   if (Kdbx_Trace(DBG_DATA_READ, addr, &buffer, sizeof(int)) != 0) {
  459.     errno = EIO;
  460.     return 0;
  461.   }
  462.   return buffer;
  463. }
  464.  
  465. /* Write a word WORD into remote address ADDR.
  466.    This goes through the data cache.  */
  467.  
  468. void
  469. remote_store_word (addr, word)
  470.      CORE_ADDR addr;
  471.      int word;
  472. {
  473.   extern CORE_ADDR text_start, text_end;
  474.   ERROR_NO_ATTACHED_HOST;
  475.   if (addr >= text_start && addr < text_end)
  476.     {
  477.       if (Kdbx_Trace(DBG_INST_WRITE, &word, addr, sizeof(word))!= 0) {
  478.     errno = EIO;
  479.       }
  480.       return;
  481.     }
  482.   if ( Kdbx_Trace(DBG_DATA_WRITE,  &word, addr, sizeof(word)) != 0) {
  483.     errno = EIO;
  484.   }
  485.   return;
  486. }
  487.  
  488. /* Write memory data directly to the remote machine.
  489.    This does not inform the data cache; the data cache uses this.
  490.    MEMADDR is the address in the remote memory space.
  491.    MYADDR is the address of the buffer in our space.
  492.    LEN is the number of bytes.  */
  493.  
  494. int
  495. remote_write_bytes (memaddr, myaddr, len)
  496.      CORE_ADDR memaddr;
  497.      char *myaddr;
  498.      int len;
  499. {
  500.   extern CORE_ADDR text_start, text_end;
  501.   ERROR_NO_ATTACHED_HOST;
  502.   if (memaddr >= text_start && memaddr < text_end)
  503.     {
  504.       return Kdbx_Trace(DBG_INST_WRITE, myaddr, memaddr, len);
  505.      }
  506.   return Kdbx_Trace(DBG_DATA_WRITE,  myaddr, memaddr, len);
  507. }
  508.  
  509. /* Read memory data directly from the remote machine.
  510.    This does not use the data cache; the data cache uses this.
  511.    MEMADDR is the address in the remote memory space.
  512.    MYADDR is the address of the buffer in our space.
  513.    LEN is the number of bytes.  */
  514.  
  515. int
  516. remote_read_bytes (memaddr, myaddr, len)
  517.      CORE_ADDR memaddr;
  518.      char *myaddr;
  519.      int len;
  520. {
  521.   int err;
  522.   ERROR_NO_ATTACHED_HOST;
  523.   return Kdbx_Trace(DBG_DATA_READ, memaddr, myaddr, len);
  524. }
  525.  
  526. #if 0
  527. /* Read LEN bytes from inferior memory at MEMADDR.  Put the result
  528.    at debugger address MYADDR.  Returns errno value.  */
  529. int
  530. remote_read_inferior_memory(memaddr, myaddr, len)
  531.      CORE_ADDR memaddr;
  532.      char *myaddr;
  533.      int len;
  534. {
  535.   int xfersize, err;
  536.   while (len > 0)
  537.     {
  538.       if (len > MAXBUFBYTES)
  539.     xfersize = MAXBUFBYTES;
  540.       else
  541.     xfersize = len;
  542.       
  543.       err = remote_read_bytes (memaddr, myaddr, xfersize);
  544.       if (err != 0) 
  545.     return err;
  546.       memaddr += xfersize;
  547.       myaddr  += xfersize;
  548.       len     -= xfersize;
  549.     }
  550.   return 0; /* no error */
  551. }
  552.  
  553. /* Copy LEN bytes of data from debugger memory at MYADDR
  554.    to inferior's memory at MEMADDR.  Returns errno value.  */
  555. int
  556. remote_write_inferior_memory (memaddr, myaddr, len)
  557.      CORE_ADDR memaddr;
  558.      char *myaddr;
  559.      int len;
  560. {
  561.   int xfersize;
  562.   int err;
  563.   while (len > 0)
  564.     {
  565.       if (len > MAXBUFBYTES)
  566.     xfersize = MAXBUFBYTES;
  567.       else
  568.     xfersize = len;
  569.       
  570.       err = remote_write_bytes(memaddr, myaddr, xfersize);
  571.       if (err != 0) {
  572.     return err;
  573.       }
  574.       
  575.       memaddr += xfersize;
  576.       myaddr  += xfersize;
  577.       len     -= xfersize;
  578.     }
  579.   return 0; /* no error */
  580. }
  581. #endif /* 0 */
  582.  
  583. /* Prepare to store registers.  Since we send them all, we have to
  584.    read out the ones we don't want to change first.  */
  585.  
  586. void 
  587. remote_prepare_to_store ()
  588. {
  589.   remote_fetch_registers (-1);
  590. }
  591.  
  592. /* Store the remote registers from the contents of the block REGS.  */
  593.  
  594. void
  595. remote_store_registers (regs,regno)
  596.      char *regs;
  597.      int    regno;
  598. {
  599.   int    i;
  600.   
  601.   ERROR_NO_ATTACHED_HOST;
  602.   if (regno < 0) { 
  603.     for (i = 0; i < 32 + 32; i++) {
  604.       Kdbx_Trace(DBG_WRITE_REG, &(((int *)regs)[i]),
  605.          Regnum_to_index(i),sizeof(int));
  606.     }    
  607.     Kdbx_Trace(DBG_WRITE_REG, ((int *)regs)+PC_REGNUM,
  608.            Regnum_to_index(PC_REGNUM),sizeof(int));
  609.     Kdbx_Trace(DBG_WRITE_REG, ((int *)regs)+HI_REGNUM,
  610.            Regnum_to_index(HI_REGNUM),sizeof(int));
  611.     Kdbx_Trace(DBG_WRITE_REG, ((int *)regs)+LO_REGNUM,
  612.            Regnum_to_index(LO_REGNUM),sizeof(int));
  613.     Kdbx_Trace(DBG_WRITE_REG, ((int *)regs)+FCRCS_REGNUM,
  614.            Regnum_to_index(FCRCS_REGNUM),sizeof(int));
  615.   } else {
  616.     int    ind = Regnum_to_index(regno);
  617.     if (ind >= 0) 
  618.       Kdbx_Trace(DBG_WRITE_REG, ((int *)regs)+regno,ind,sizeof(int));
  619.     else
  620.       remote_write_bytes(((int *) regs)[SP_REGNUM], 
  621.              ((int *) regs) + regno,4);
  622.   }
  623. }
  624.  
  625. /* Read or write LEN bytes from inferior memory at MEMADDR, transferring
  626.    to or from debugger address MYADDR.  Write to inferior if SHOULD_WRITE is
  627.    nonzero.  Returns length of data written or read; 0 for error.  */
  628.  
  629. /* ARGSUSED */
  630. int
  631. remote_xfer_memory(memaddr, myaddr, len, should_write, target)
  632.      CORE_ADDR memaddr;
  633.      char *myaddr;
  634.      int len;
  635.      int should_write;
  636.      struct target_ops *target;            /* ignored */
  637. {
  638.   int origlen = len;
  639.   int xfersize;
  640.   while (len > 0)
  641.     {
  642.       if (len > MAXBUFBYTES)
  643.     xfersize = MAXBUFBYTES;
  644.       else
  645.     xfersize = len;
  646.  
  647.       if (should_write) {
  648.     if (errno = remote_write_bytes(memaddr, myaddr, xfersize)) {
  649.         return 0;
  650.     }
  651.       } else {
  652.     if (errno = remote_read_bytes (memaddr, myaddr, xfersize)) {
  653.         return 0;
  654.     }
  655.       }
  656.       memaddr += xfersize;
  657.       myaddr  += xfersize;
  658.       len     -= xfersize;
  659.     }
  660.   return origlen; /* no error possible */
  661. }
  662.  
  663. /* 
  664.  * Call a remote function.
  665.  */
  666. call_remote_function(funaddr,nargs,numBytes,argBuffer)
  667.      CORE_ADDR funaddr;
  668.      int        nargs;
  669.      int        numBytes;
  670.      char    *argBuffer;
  671. {
  672.   int    returnValue;
  673.   ERROR_NO_ATTACHED_HOST;
  674.   Kdbx_Trace(DBG_BEGIN_CALL, (char *)0, (char *)0, 0);  
  675.   returnValue = Kdbx_Trace(DBG_CALL_FUNCTION,argBuffer,funaddr,numBytes);
  676.   Kdbx_Trace(DBG_END_CALL, (char *)0, (char *)0, 0);       
  677.   return returnValue;
  678. }
  679.  
  680. void
  681. remote_close(quitting)
  682.      int quitting;
  683. {
  684. }
  685.  
  686. remote_clean_up()
  687. {
  688.   MARK_DISCONNECTED;
  689. }
  690.  
  691.  
  692. read_kmem(memaddr, myaddr, len)
  693.      char *memaddr;
  694.      char *myaddr;
  695.      int      len;
  696. {
  697.   static int fd = -1;
  698.   int count;
  699.   
  700.   if (fd < 0) { 
  701.     char template[100];
  702.     /*
  703.      * Open a temp file to write counters to. We unlink the file so it will
  704.      * disappear when we exit.
  705.      */
  706.     strcpy(template, "/tmp/kgdbXXXXXXXX");
  707.     fd = mkstemp(template);
  708.     if (fd < 0) {
  709.       error("open kmem tmp file");
  710.     }
  711.     (void) unlink(template);
  712.   }
  713.   if (lseek(fd, 0, L_SET) < 0) {
  714.     error("lseek kmem file");
  715.   }
  716.   count = write(fd, memaddr, len);
  717.   if (count != len) {
  718.     return EIO;
  719.   }
  720.   
  721.   /*
  722.    * Rewind the file and read the counters from it.
  723.    */
  724.   count = lseek(fd, 0, L_SET);
  725.   if (count >= 0) {
  726.     count = read(fd, myaddr, len);
  727.   }
  728.   if (count != len) {
  729.     return EIO;
  730.   }
  731.   return 0;
  732. }
  733.  
  734. void
  735. remote_reboot (args)
  736.      char *args;
  737. {
  738.   
  739.   ERROR_NO_ATTACHED_HOST;
  740.   if (!args)
  741.     args = "";
  742.   
  743.   Kdbx_Trace(DBG_REBOOT, args, NULL, strlen(args));
  744. }
  745.  
  746. void
  747. remote_files_info ()
  748. {
  749.   printf ("remote files info missing here.  FIXME.\n");
  750. }
  751.  
  752. struct target_ops remote_ops = {
  753.   "remote", "Remote serial target in gdb-specific protocol",
  754.   "Use a remote computer via a serial line, using a gdb-specific protocol.\n\
  755.  Specify the serial device it is connected to (e.g. /dev/ttya).", 
  756.     remote_open, 
  757.     remote_close, 
  758.     remote_attach,
  759.     remote_detach, 
  760.     remote_resume, 
  761.     remote_wait, /* attach */ 
  762.     remote_fetch_registers, 
  763.     remote_store_registers, 
  764.     remote_prepare_to_store, 
  765.     0, 0, /* conv_from, conv_to */ 
  766.     remote_xfer_memory, 
  767.     remote_files_info, 
  768.     0, 0, /* insert and remove breakpoint */
  769.     0, 0, 0, 0, 0, /* Terminal crud */ 
  770.     remote_detach, /* kill */ 
  771.     0, /* load */ 
  772.     0, /* lookup_symbol */ 
  773.     0, 0, /* create_inferior FIXME, mourn_inferior FIXME */ 
  774.     process_stratum, 0, /* next */ 
  775.     1, 1, 1, 1, 1, /* all mem, mem, stack, regs, exec */ 
  776.     0, 0, /* Section pointers */ 
  777.     OPS_MAGIC, /* Always the last thing */
  778.   };
  779.  
  780. void
  781. _initialize_remote ()
  782. {
  783.   add_target (&remote_ops);
  784. }
  785.  
  786. #include <sys/types.h>
  787. #include <sys/socket.h>
  788. #include <sys/time.h>
  789. #include <netinet/in.h>
  790. #include <netdb.h>
  791. #include <sgtty.h>
  792.  
  793. /*
  794.  * Direct mapped cache of data and code.   The cache is flushed after every
  795.  * step and continue by incrementing the version number.  Flushing code
  796.  * isn't necessary but since kdbx already has an internal code cache it
  797.  * doesn't hurt and makes life easier.
  798.  */
  799. static    int    cacheBlockSize = -1;
  800. static    int    cacheBlockShift = -1;
  801. static    int    cacheSize = 128 * 1024;
  802. #define    CACHE_BLOCK_MASK     (cacheSize / cacheBlockSize - 1)
  803. #define    CACHE_BLOCK_OFFSET_MASK    (cacheBlockSize - 1)
  804. #define    NUM_CACHE_BLOCKS    (cacheSize >> cacheBlockShift)
  805. #define    CACHE_OFFSET_MASK    (cacheSize - 1)
  806. #define    GET_CACHE_BLOCK(address) (((unsigned int) address) >> cacheBlockShift)
  807.  
  808. /*
  809.  * Stuff for the serial port.
  810.  */
  811. static    int    kernChannel = 0;
  812.  
  813.  
  814. /*
  815.  * Message buffers.
  816.  */
  817. static Dbg_Msg    msg;
  818. static int    msgSize;
  819. #define    REPLY_BUFFER_SIZE    16384
  820. static    char    replyBuffer[REPLY_BUFFER_SIZE];
  821. static    char    requestBuffer[DBG_MAX_REQUEST_SIZE];
  822. /*
  823.  * The starting message number is set to 0x40000000 so that the debugger
  824.  * stub can differentiate between messages from kgdb and kdbx.  Once
  825.  * kdbx is gone the msgNum can be initialized to 0.
  826.  */
  827. #ifdef KDBX
  828. #define FIRST_MSG 0x40000000
  829. static    int    msgNum = FIRST_MSG;
  830. #else
  831. static    int    msgNum = 0;
  832. #endif
  833.  
  834. static void    RecvReply();
  835.  
  836. static    struct sockaddr_in    remote;
  837. static    int            kdbxTimeout = 1;
  838. static    int            netSocket;
  839.  
  840.  
  841. /*
  842.  *----------------------------------------------------------------------
  843.  *
  844.  * CreateSocket --
  845.  *
  846.  *    Creates a UDP socket connected to the Sprite host's kernel 
  847.  *    debugger port.
  848.  *
  849.  * Results:
  850.  *    The stream ID of the socket.
  851.  *
  852.  * Side effects:
  853.  *    None.
  854.  *
  855.  *----------------------------------------------------------------------
  856.  */
  857. static int
  858. CreateSocket(spriteHostName)
  859.     char    *spriteHostName;
  860. {
  861.     int            socketID;
  862.     struct hostent     *hostPtr;
  863.  
  864.     hostPtr = gethostbyname(spriteHostName);
  865.     if (hostPtr == (struct hostent *) NULL) {
  866.     error("CreateSocket: unknown host %s\n", spriteHostName);
  867.     }
  868.     if (hostPtr->h_addrtype != AF_INET) {
  869.     error("CreateSocket: bad address type for host %s\n", 
  870.         spriteHostName);
  871.     }
  872.  
  873.     socketID = socket(AF_INET, SOCK_DGRAM, 0);
  874.     if (socketID < 0) {
  875.     perror_with_name("CreateSocket: socket");
  876.     }
  877.  
  878.     bzero((Address)&remote, sizeof(remote));
  879.     bcopy(hostPtr->h_addr, (Address)&remote.sin_addr, hostPtr->h_length);
  880.     remote.sin_port = htons(DBG_UDP_PORT);
  881.     remote.sin_family = AF_INET;
  882.  
  883.     if (connect(socketID, (struct sockaddr *) &remote, sizeof(remote)) < 0) {
  884.     perror_with_name("CreateSocket: connect");
  885.     }
  886.  
  887.     return(socketID);
  888. }
  889.  
  890.  
  891. /*
  892.  * ----------------------------------------------------------------------------
  893.  *
  894.  *  StartDebugger --
  895.  *
  896.  *     Start off a new conversation with the debugger.
  897.  *
  898.  * Results:
  899.  *     None.
  900.  *
  901.  * Side effects:
  902.  *     Setup r network socket.
  903.  * ----------------------------------------------------------------------------
  904.  */
  905. static void
  906. StartDebugger()
  907. {
  908.         char    *host = hostName;
  909.     hostName = (char *) 0;
  910.     netSocket = CreateSocket(host);
  911.     hostName = host;
  912. }
  913.  
  914.  
  915. /*
  916.  * ----------------------------------------------------------------------------
  917.  *
  918.  *  SendRequest --
  919.  *
  920.  *     Send a request message to the kernel.
  921.  *
  922.  * Results:
  923.  *     None.
  924.  *
  925.  * Side effects:
  926.  *     None.
  927.  * ----------------------------------------------------------------------------
  928.  */
  929. static void
  930. SendRequest(numBytes, newRequest)
  931.     int        numBytes;
  932.     Boolean    newRequest;
  933. {
  934.      {
  935.     Dbg_Opcode    opcode;
  936.  
  937.     msgSize = numBytes;
  938.     if (newRequest) {
  939.         msgNum++;
  940.     }
  941.     *(int *)requestBuffer = msgNum;
  942.     bcopy(&msg, requestBuffer + 4, numBytes);
  943.     if (write(netSocket, requestBuffer, numBytes + 4) < numBytes + 4) {
  944.       MARK_DISCONNECTED;
  945.       perror_with_name("SendRequest: Couldn't write to the kernel socket\n");
  946.       return;
  947.     }
  948.     if (newRequest) {
  949.       opcode = (Dbg_Opcode) msg.opcode;
  950.       if (opcode == DBG_DETACH || opcode == DBG_CONTINUE ||
  951.           opcode == DBG_SINGLESTEP || opcode == DBG_DIVERT_SYSLOG || 
  952.           opcode == DBG_BEGIN_CALL || 
  953.           opcode == DBG_WRITE_REG || opcode == DBG_SET_PID) {
  954.         int    dummy;
  955.         /*
  956.          * Wait for explicit acknowledgments of these packets.
  957.          */
  958.         RecvReply(opcode, 4, &dummy, NULL, 1);
  959.       }
  960.     }
  961.     }
  962. }
  963.  
  964.  
  965. /*
  966.  * ----------------------------------------------------------------------------
  967.  *
  968.  *  RecvReply --
  969.  *
  970.  *     Receive a reply from the kernel.
  971.  *
  972.  * Results:
  973.  *     None.
  974.  *
  975.  * Side effects:
  976.  *     None.
  977.  * ----------------------------------------------------------------------------
  978.  */
  979. static void
  980. RecvReply(opcode, numBytes, destAddr, readStatusPtr, timeout)
  981.     Dbg_Opcode    opcode;
  982.     int        numBytes;
  983.     char    *destAddr;
  984.     int    *readStatusPtr;
  985.     int    timeout;
  986. {
  987.     int        status;
  988.     int     resendRequest = 0;
  989.  
  990.     if (numBytes + 8 > REPLY_BUFFER_SIZE) {
  991.     fprintf(stderr,"numBytes <%d> > REPLY_BUFFER_SIZE <%d>\n",
  992.             numBytes + 8, REPLY_BUFFER_SIZE);
  993.     abort();
  994.     }
  995.      {
  996.     int        readMask;
  997.     struct    timeval    interval;
  998.     int        bytesRead;
  999.  
  1000.     interval.tv_sec = kdbxTimeout;
  1001.     interval.tv_usec = 0;
  1002.     do {
  1003.         if (timeout) {
  1004.         int    numTimeouts;
  1005.  
  1006.         numTimeouts = 0;
  1007.         /*
  1008.          * Loop timing out and sending packets until a new packet
  1009.          * has arrived.
  1010.          */
  1011.         do {
  1012.             if (!resendRequest) { 
  1013.             readMask = 1 << netSocket;
  1014.             status = select(32, &readMask, NULL, NULL, &interval);
  1015.             } else {
  1016.             status = 0;
  1017.             resendRequest = 0;
  1018.             }
  1019.             if (status == 1) {
  1020.             break;
  1021.             } else if (status == -1) {
  1022.                 MARK_DISCONNECTED;
  1023.             perror_with_name("RecvReply: Couldn't select on socket.\n");
  1024.             } else if (status == 0) {
  1025.             SendRequest(msgSize, 0);
  1026.             numTimeouts++;
  1027.             if (numTimeouts % 10 == 0) {
  1028.                 fprintf(stderr, 
  1029.                     "Timing out and resending to host %s\n",
  1030.                     hostName);
  1031.                 fflush(stderr);
  1032.                 QUIT;
  1033.             }
  1034.             }
  1035.         } while (1);
  1036.         }
  1037.         if (opcode == DBG_DATA_READ || opcode == DBG_INST_READ ||
  1038.         opcode == DBG_GET_VERSION_STRING) {
  1039.         /*
  1040.          * Data and instruction reads return variable size packets.
  1041.          * The first two ints are message number and status.  If
  1042.          * the status is OK then the data follows.
  1043.          */
  1044.         immediate_quit++;
  1045.         bytesRead = read(netSocket, replyBuffer, numBytes + 8);
  1046.         immediate_quit--;
  1047.         if (bytesRead < 0) {
  1048.             MARK_DISCONNECTED;
  1049.             perror_with_name("RecvReply: Error reading socket.");
  1050.         }
  1051.         /*
  1052.          * Check message number before the size because this could
  1053.          * be an old packet.
  1054.          */
  1055.         if (*(int *)replyBuffer != msgNum) {
  1056. #ifdef KDBX
  1057.             printf("RecvReply: Old message number = %d, expecting %d\n",
  1058.                 *(int *)replyBuffer - FIRST_MSG, 
  1059.                 msgNum - FIRST_MSG);
  1060. #else
  1061.             printf("RecvReply: Old message number = %d, expecting %d\n",
  1062.                 *(int *)replyBuffer, msgNum);
  1063. #endif
  1064.             fflush(stdout);
  1065.             resendRequest = 1;
  1066.             continue;
  1067.         }
  1068.         if (bytesRead == 8) {
  1069.             /*
  1070.              * Only 8 bytes so the read failed and there is no data.
  1071.              */
  1072.             *readStatusPtr = 0;
  1073.             return;
  1074.         }
  1075.             if (opcode == DBG_GET_VERSION_STRING) {
  1076.              strncpy(destAddr, (char *)(replyBuffer + 4),numBytes);
  1077.              return;
  1078.         }
  1079.         if (bytesRead != numBytes + 8) {
  1080.             printf("RecvReply: Short read (1): op=%d exp=%d read=%d",
  1081.                 opcode, numBytes + 4, bytesRead);
  1082.             continue;
  1083.         }
  1084.         *readStatusPtr = 1;
  1085.         bcopy(replyBuffer + 8, destAddr, numBytes);
  1086.         return;
  1087.         } else if (opcode == DBG_END_CALL) {
  1088.         int    length;
  1089.         /*
  1090.          * End call returns a variable size packet that contains
  1091.          * the result of the call. The format of the message is 
  1092.          * message number, length, data.
  1093.          */
  1094.         immediate_quit++;
  1095.         bytesRead = read(netSocket, replyBuffer, REPLY_BUFFER_SIZE);
  1096.         immediate_quit--;
  1097.         if (bytesRead < 0) {
  1098.             MARK_DISCONNECTED;
  1099.             perror_with_name("RecvReply: Error reading socket.");
  1100.         }
  1101.         /*
  1102.          * Check message number before the size because this could
  1103.          * be an old packet.
  1104.          */
  1105.         if (*(int *)replyBuffer != msgNum) {
  1106. #ifdef KDBX
  1107.             printf("RecvReply: Old message number = %d, expecting %d\n",
  1108.                 *(int *)replyBuffer - FIRST_MSG, 
  1109.                 msgNum - FIRST_MSG);
  1110. #else
  1111.             printf("RecvReply: Old message number = %d, expecting %d\n",
  1112.                 *(int *)replyBuffer, msgNum);
  1113. #endif
  1114.             fflush(stdout);
  1115.             resendRequest = 1;
  1116.             continue;
  1117.         }
  1118.         length = *( int *)(replyBuffer + 4);
  1119.         if (bytesRead - 8 != length) {
  1120.             fprintf(stderr, "RecvReply: Short read for syslog data\n");
  1121.             fprintf(stderr, "RecvReply: Read %d, length %d\n", 
  1122.             bytesRead - 8, length);
  1123.             fflush(stderr);
  1124.             length = bytesRead - 8;
  1125.         }
  1126.         if (length <= 0) {
  1127.             /*
  1128.              * No data.
  1129.              */
  1130.             *readStatusPtr = 0;
  1131.             return;
  1132.         }
  1133.         /*
  1134.          * Dump out the buffer.
  1135.          */
  1136.         write(1, replyBuffer + 8, length);
  1137.         *readStatusPtr = 1;
  1138.         return;
  1139.         } else {
  1140.         /*
  1141.          * Normal request so just read in the message which includes
  1142.          * the message number.
  1143.          */
  1144.         immediate_quit++;
  1145.         bytesRead = read(netSocket, replyBuffer, numBytes + 4);
  1146.         immediate_quit--;
  1147.         if (bytesRead < 0) {
  1148.             MARK_DISCONNECTED;
  1149.             perror_with_name("RecvReply: Error reading socket (2).");
  1150.         }
  1151.         /*
  1152.          * Check message number before size because it could be
  1153.          * an old packet.
  1154.          */
  1155.         if (*(int *)replyBuffer != msgNum) {
  1156. #ifdef KDBX
  1157.             printf("RecvReply: Old message number = %d, expecting %d\n",
  1158.                 *(int *)replyBuffer - FIRST_MSG, 
  1159.                 msgNum - FIRST_MSG);
  1160. #else
  1161.             printf("RecvReply: Old message number = %d, expecting %d\n",
  1162.                 *(int *)replyBuffer, msgNum);
  1163. #endif
  1164.             fflush(stdout);
  1165.             resendRequest = 1;
  1166.             continue;
  1167.         }
  1168.         if (bytesRead != numBytes + 4) {
  1169.             printf("RecvReply: Short read (2): op=%d exp=%d read=%d",
  1170.                 opcode, numBytes + 4, bytesRead);
  1171.         }
  1172.         if (*(int *)replyBuffer != msgNum) {
  1173.             continue;
  1174.         }
  1175.         bcopy(replyBuffer + 4, destAddr, numBytes);
  1176.         return;
  1177.         }
  1178.     } while (1);
  1179.     }
  1180. }
  1181.  
  1182.  
  1183. /*
  1184.  * ----------------------------------------------------------------------------
  1185.  *
  1186.  *  WaitForKernel --
  1187.  *
  1188.  *      Wait for the kernel to send us a message to indicate that it is waiting
  1189.  *    to be debugged.
  1190.  *
  1191.  * Results:
  1192.  *     None.
  1193.  *
  1194.  * Side effects:
  1195.  *     None.
  1196.  * ----------------------------------------------------------------------------
  1197.  */
  1198. static void
  1199. WaitForKernel()
  1200. {
  1201.     int    dummy;
  1202.  
  1203.     RecvReply(DBG_CONTINUE, 4, &dummy, NULL, 0);
  1204. }
  1205.  
  1206.  
  1207. /*
  1208.  * ----------------------------------------------------------------------------
  1209.  *
  1210.  * BlockInCache --
  1211.  *
  1212.  *     See if the given block at the given address is in the cache.
  1213.  *
  1214.  * Results:
  1215.  *     1 if found block in cache, 0 if didn't.
  1216.  *
  1217.  * Side effects:
  1218.  *     None.
  1219.  */
  1220. static int
  1221. BlockInCache(blockNum, addr)
  1222.     int        blockNum;
  1223.     char    *addr;
  1224. {
  1225.     blockNum = blockNum & CACHE_BLOCK_MASK;
  1226.     return((int) (cacheInfo[blockNum].version == currentVersion &&
  1227.        (unsigned int) cacheInfo[blockNum].realAddr == 
  1228.             ((unsigned int) (addr) & ~CACHE_BLOCK_OFFSET_MASK)));
  1229. }
  1230.  
  1231.  
  1232. /*
  1233.  * ----------------------------------------------------------------------------
  1234.  *
  1235.  * FetchBlock --
  1236.  *
  1237.  *     Fetch the given data block from the cache or the kernel if necessary.
  1238.  *
  1239.  * Results:
  1240.  *     1 if could fetch block into cache, 0 if couldn't.
  1241.  *
  1242.  * Side effects:
  1243.  *     Data cache modified.
  1244.  *
  1245.  * ----------------------------------------------------------------------------
  1246.  */
  1247. static int
  1248. FetchBlock(blockNum, srcAddr, opcode)
  1249.     int        blockNum;
  1250.     char    *srcAddr;
  1251.     Dbg_Opcode    opcode;
  1252. {
  1253.     int    successfulRead;
  1254.  
  1255.     blockNum = blockNum & CACHE_BLOCK_MASK;
  1256.     srcAddr = (char *) ((unsigned int) (srcAddr) & ~CACHE_BLOCK_OFFSET_MASK);
  1257.  
  1258.     if (BlockInCache(blockNum, srcAddr)) {
  1259.     return(1);
  1260.     }
  1261.     msg.opcode = opcode;
  1262.     msg.data.readMem.address = (int) srcAddr;
  1263.     msg.data.readMem.numBytes = cacheBlockSize;
  1264.     SendRequest(sizeof(msg.opcode) + sizeof(Dbg_ReadMem), 1);
  1265.     RecvReply(opcode, cacheBlockSize, 
  1266.         &dataCache[(unsigned int) (srcAddr) & CACHE_OFFSET_MASK],
  1267.         &successfulRead, 1);
  1268.     if (successfulRead) {
  1269.     cacheInfo[blockNum].version = currentVersion;
  1270.     cacheInfo[blockNum].realAddr = srcAddr;
  1271.     }
  1272.     return(successfulRead);
  1273. }
  1274.  
  1275.  
  1276.  
  1277. /*
  1278.  * ----------------------------------------------------------------------------
  1279.  *
  1280.  * Kdbx_Trace --
  1281.  *
  1282.  *     Write the trace command over to the kernel.  
  1283.  *
  1284.  * Results:
  1285.  *     None.
  1286.  *
  1287.  * Side effects:
  1288.  *     None.
  1289.  *
  1290.  * ----------------------------------------------------------------------------
  1291.  */
  1292. int 
  1293. Kdbx_Trace(opcode, srcAddr, destAddr, numBytes)
  1294.     Dbg_Opcode    opcode;        /* Which command */
  1295.     char    *srcAddr;    /* Where to read data from */
  1296.     char    *destAddr;    /* Where to write data to */
  1297.     int        numBytes;    /* The number of bytes to read or write */
  1298. {
  1299.     int            (*intrHandler)();
  1300.     int            i;
  1301.     int            retVal = 0;
  1302.     if (!initialized) {
  1303.     int    moreData;
  1304.     /*
  1305.      * Setup the cache and initiate a conversation with the other kernel.
  1306.      */
  1307.     if (cacheBlockSize == -1) {
  1308.          {
  1309.         cacheBlockSize = 256;
  1310.         cacheBlockShift = 8;
  1311.         }
  1312.     }
  1313.     dataCache = (char *) malloc(cacheSize);
  1314.     cacheInfo = (CacheInfo *) malloc(NUM_CACHE_BLOCKS * sizeof(CacheInfo));
  1315.     for (i = 0; i < NUM_CACHE_BLOCKS; i++) {
  1316.         cacheInfo[i].version = 0;
  1317.     }
  1318.     StartDebugger();
  1319.     /*
  1320.      * Dump the system log by faking a call command.
  1321.      */
  1322.     printf("Dumping system log ...\n");
  1323.     fflush(stdout);
  1324.     msg.opcode = (short)DBG_BEGIN_CALL;
  1325.     SendRequest(sizeof(msg.opcode), 1);
  1326.     msg.opcode = (short)DBG_END_CALL;
  1327.     do {
  1328.         SendRequest(sizeof(msg.opcode), 1);
  1329.         RecvReply(msg.opcode, 0, NULL, &moreData, 1);
  1330.     } while (moreData);
  1331.     initialized = 1;
  1332.     }
  1333.  
  1334.  
  1335.     if (opcode == DBG_DATA_READ || opcode == DBG_INST_READ) {
  1336.     int            firstBlock;
  1337.     int            lastBlock;
  1338.     unsigned    int    cacheOffset;
  1339.     int            toRead;
  1340.  
  1341.     /*
  1342.      * Read using the cache.
  1343.      */
  1344.     firstBlock = GET_CACHE_BLOCK(srcAddr); 
  1345.     lastBlock = GET_CACHE_BLOCK(srcAddr + numBytes - 1);
  1346.     for (i = firstBlock; i <= lastBlock; i++) {
  1347.         cacheOffset = ((unsigned int) srcAddr) & CACHE_OFFSET_MASK;
  1348.         if (i == lastBlock) {
  1349.         toRead = numBytes;
  1350.         } else if (i == firstBlock) {
  1351.         toRead = cacheBlockSize - 
  1352.                 (cacheOffset & CACHE_BLOCK_OFFSET_MASK);
  1353.         } else {
  1354.         toRead = cacheBlockSize;
  1355.         }
  1356.         if (!FetchBlock(i, srcAddr, opcode)) {
  1357.         return EIO;
  1358.         }
  1359.         bcopy(&dataCache[cacheOffset], destAddr, toRead);
  1360.         srcAddr += toRead;
  1361.         destAddr += toRead;
  1362.         numBytes -= toRead;
  1363.     }
  1364.     return(0);
  1365.     }
  1366.  
  1367.     if (opcode == DBG_DATA_WRITE || opcode == DBG_INST_WRITE) {
  1368.     int    firstBlock;
  1369.     int    lastBlock;
  1370.     int    cacheOffset;
  1371.     int    toWrite;
  1372.     char    *tSrcAddr;
  1373.     char    *tDestAddr;
  1374.     int    tNumBytes;
  1375.  
  1376.     /*
  1377.      * If the block that is being fetched is in the cache then write the
  1378.      * data there first before sending it over to the kernel.
  1379.      */
  1380.     tSrcAddr = srcAddr;
  1381.     tDestAddr = destAddr;
  1382.     tNumBytes = numBytes;
  1383.  
  1384.     firstBlock = GET_CACHE_BLOCK(destAddr); 
  1385.     lastBlock = GET_CACHE_BLOCK(destAddr + numBytes - 1);
  1386.     for (i = firstBlock; i <= lastBlock; i++) {
  1387.         cacheOffset = ((int) tDestAddr) & CACHE_OFFSET_MASK;
  1388.         if (i == lastBlock) {
  1389.         toWrite = tNumBytes;
  1390.         } else if (i == firstBlock) {
  1391.         toWrite = cacheBlockSize - 
  1392.                 (cacheOffset & CACHE_BLOCK_OFFSET_MASK);
  1393.         } else {
  1394.         toWrite = cacheBlockSize;
  1395.         }
  1396.         if (BlockInCache(i, tDestAddr)) {
  1397.         bcopy(tSrcAddr, &dataCache[cacheOffset], tNumBytes);
  1398.         }
  1399.         tSrcAddr += toWrite;
  1400.         tDestAddr += toWrite;
  1401.         tNumBytes -= toWrite;
  1402.     }
  1403.     }
  1404.  
  1405.     msg.opcode = (short) opcode;
  1406.  
  1407.     /*
  1408.      * Do the rest of the work for the desired operation.
  1409.      */
  1410.  
  1411.     switch (opcode) {
  1412.  
  1413.     /*
  1414.      * For these operations the desired data is read from the other
  1415.      * kernel and stored at destAddr.
  1416.      */
  1417.     case DBG_READ_ALL_REGS:
  1418.     case DBG_GET_STOP_INFO:
  1419.         SendRequest(sizeof(msg.opcode), 1);
  1420.         RecvReply(opcode, numBytes, destAddr, NULL, 1);
  1421.         break;
  1422.  
  1423.     /*
  1424.      * For this operation the desired data is read from srcAddr
  1425.      * and written to the other kernel.
  1426.      */
  1427.     case DBG_SET_PID:
  1428.         msg.data.pid = *(int *)srcAddr;
  1429.         SendRequest(sizeof(msg.opcode) + sizeof(msg.data.pid), 1);
  1430.         break;
  1431.  
  1432.     /*
  1433.      * When writing a general purpose register first the address to write
  1434.      * that is stored in destAddr must be given to the other kernel.
  1435.      * Then the data itself which is stored at srcAddr can be written over.
  1436.      */
  1437.     case DBG_WRITE_REG:
  1438.         msg.data.writeReg.regNum = (int) destAddr;
  1439.         msg.data.writeReg.regVal = *(int *) srcAddr;
  1440.         SendRequest(sizeof(msg.opcode) + sizeof(Dbg_WriteReg), 1);
  1441.         break;
  1442.  
  1443.     /*
  1444.      * When writing to the kernels instruction or data space first the
  1445.      * address of where to write to (destAddr) and then the number of
  1446.      * bytes to write (numBytes) must be sent over.  Finally all of
  1447.      * the data is read from srcAddr and written over.
  1448.      */
  1449.  
  1450.     case DBG_INST_WRITE:
  1451.     case DBG_DATA_WRITE: {
  1452.         char    writeStatus;
  1453.  
  1454.         msg.data.writeMem.address = (int) destAddr;
  1455.         msg.data.writeMem.numBytes = numBytes;
  1456.         bcopy(srcAddr, msg.data.writeMem.buffer, numBytes);
  1457.         SendRequest(sizeof(msg.opcode) + 2 * sizeof(int) + numBytes, 1);
  1458.         RecvReply(opcode, 1, &writeStatus, NULL, 1);
  1459.         if (writeStatus == 0) {
  1460.         retVal = EIO;
  1461.         fprintf(stderr, "ERROR: invalid write address 0x%x\n",destAddr);
  1462.         } 
  1463.         break;
  1464.     }
  1465.     case DBG_DIVERT_SYSLOG:
  1466.         msg.data.syslogCmd = (Dbg_SyslogCmd)srcAddr;
  1467.         SendRequest(sizeof(msg.opcode) + sizeof(Dbg_SyslogCmd), 1);
  1468.         break;
  1469.     case DBG_BEGIN_CALL:
  1470.         SendRequest(sizeof(msg.opcode), 1);
  1471.         break;
  1472.     case DBG_END_CALL: {
  1473.         Boolean    moreData;
  1474.         do {
  1475.         SendRequest(sizeof(msg.opcode), 1);
  1476.         RecvReply(opcode, 0, NULL, &moreData, 1);
  1477.         } while (moreData);
  1478.         break;
  1479.     }
  1480.  
  1481.     case DBG_DETACH: {
  1482.         msg.opcode = (short) DBG_DIVERT_SYSLOG;
  1483.         msg.data.syslogCmd = DBG_SYSLOG_TO_ORIG;
  1484.         SendRequest(sizeof(msg.opcode) + sizeof(Dbg_SyslogCmd), 1);
  1485.  
  1486.         msg.opcode = (short) DBG_DETACH;
  1487.         msg.data.pc = *(int *) srcAddr;
  1488.         SendRequest(sizeof(msg.opcode) + sizeof(msg.data.pc), 1);
  1489.         break;
  1490.     }
  1491.  
  1492.     case DBG_CONTINUE:
  1493.     case DBG_SINGLESTEP:
  1494.         SendRequest(sizeof(msg.opcode) + sizeof(msg.data.pc), 1);
  1495.         currentVersion++;
  1496.         WaitForKernel();
  1497.         break;
  1498.  
  1499.     case DBG_CALL_FUNCTION: {
  1500.         int        returnValue;
  1501.  
  1502.         msg.data.callFunc.address = (int) destAddr;
  1503.         msg.data.callFunc.numBytes = numBytes;
  1504.         bcopy(srcAddr, msg.data.callFunc.buffer, numBytes);
  1505.         SendRequest(sizeof(msg.opcode) + 2 * sizeof(int) + numBytes, 1);
  1506.         RecvReply(opcode, sizeof(returnValue), &returnValue, NULL, 1);
  1507.         return (returnValue);
  1508.     }
  1509.     case DBG_REBOOT: {
  1510.         msg.data.reboot.stringLength = numBytes;
  1511.         bcopy(srcAddr, msg.data.reboot.string, numBytes);
  1512.         SendRequest(sizeof(msg.opcode) + sizeof(int) + numBytes, 1);
  1513.         return (0);
  1514.     }
  1515.     case DBG_GET_VERSION_STRING: {
  1516.         SendRequest(sizeof(msg.opcode), 1);
  1517.         RecvReply(opcode,numBytes , destAddr, NULL, 1);
  1518.         return (0);
  1519.     }
  1520.     default:
  1521.         printf("Unknown opcode %d\n", opcode);
  1522.         return(-1);
  1523.     }
  1524.     return(retVal);
  1525. }
  1526.  
  1527.  
  1528.  
  1529.  
  1530.  
  1531.  
  1532.  
  1533.  
  1534.  
  1535.